﻿namespace AC.ExtendedRenderer.Toolkit.Charting
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Globalization;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    public class HBarChart : UserControl
    {
        private CBackgroundProperty background;
        protected HItems bars;
        private Bitmap bmpBackBuffer;
        private IContainer components;
        private CDescriptionProperty description;
        private CLabelProperty label;
        private int nBarsGap;
        private int nBarWidth;
        public BarSizingMode SizingMode;
        protected ToolTip tooltip;
        private CValueProperty values;

        public HBarChart()
        {
            this.InitializeComponent();
            this.description = new CDescriptionProperty();
            this.label = new CLabelProperty();
            this.values = new CValueProperty();
            this.background = new CBackgroundProperty();
            this.nBarWidth = 0x18;
            this.nBarsGap = 4;
            this.SizingMode = BarSizingMode.Normal;
            this.bars = new HItems();
            this.bmpBackBuffer = null;
            this.tooltip = new ToolTip();
            this.tooltip.IsBalloon = true;
            this.tooltip.ShowAlways = true;
            this.tooltip.InitialDelay = 0;
            this.tooltip.ReshowDelay = 0;
            this.tooltip.AutoPopDelay = 0x7fff;
        }

        public void Add(double dValue, string strLabel, Color colorBar)
        {
            this.bars.Add(dValue, strLabel, colorBar);
        }

        private void CreateDescFont(Graphics gr, SizeF sizeBound)
        {
            string name;
            FontStyle regular;
            float emSize = sizeBound.Height / 15f;
            if (emSize <= 0f)
            {
                emSize = 1f;
            }
            if (this.description.Font == null)
            {
                name = "Tahoma";
                regular = FontStyle.Regular;
            }
            else
            {
                name = this.description.Font.Name;
                regular = this.description.Font.Style;
            }
            this.description.Font = new Font(name, emSize, regular);
            SizeF ef = gr.MeasureString(this.description.Text, this.description.Font);
            if (ef.Width > sizeBound.Width)
            {
                float num2 = (sizeBound.Width - (2 * this.nBarsGap)) / ef.Width;
                emSize = this.description.Font.Size * num2;
                if (emSize > 0f)
                {
                    this.description.Font.Dispose();
                    this.description.Font = null;
                    this.description.Font = new Font(name, emSize, regular);
                }
            }
        }

        private void CreateLabelFont(Graphics gr, SizeF sizeBar)
        {
            string name;
            FontStyle regular;
            SizeF ef2;
            float emSize = 100f + (sizeBar.Width / 24f);
            if (emSize <= 0f)
            {
                emSize = 1f;
            }
            if (this.Label.Font == null)
            {
                name = "Tahoma";
                regular = FontStyle.Regular;
            }
            else
            {
                name = this.Label.Font.Name;
                regular = this.Label.Font.Style;
            }
            this.Label.Font = new Font(name, emSize, regular);
            HBarData bar = null;
            SizeF ef = new SizeF(0f, 0f);
            for (int i = 0; i < this.bars.Count; i++)
            {
                if (this.bars.GetAt(i, out bar))
                {
                    ef2 = gr.MeasureString(bar.Label, this.Label.Font);
                    if (ef2.Width > ef.Width)
                    {
                        ef = ef2;
                    }
                }
            }
            ef2 = ef;
            if (ef2.Width > sizeBar.Width)
            {
                float num3 = sizeBar.Width / ef2.Width;
                emSize = this.Label.Font.Size * num3;
                if (emSize > 0f)
                {
                    this.Label.Font.Dispose();
                    this.Label.Font = null;
                    this.Label.Font = new Font(name, emSize, regular);
                }
            }
        }

        private void CreateValueFont(Graphics gr, SizeF sizeBar)
        {
            string name;
            FontStyle regular;
            float emSize = 100f + (sizeBar.Width / 24f);
            if (emSize <= 0f)
            {
                emSize = 1f;
            }
            if (this.Values.Font == null)
            {
                name = "Tahoma";
                regular = FontStyle.Regular;
            }
            else
            {
                name = this.Values.Font.Name;
                regular = this.Values.Font.Style;
            }
            this.Values.Font = new Font(name, emSize, regular);
            HBarData bar = null;
            string text = string.Empty;
            string str3 = string.Empty;
            double totalValue = this.bars.TotalValue;
            for (int i = 0; i < this.bars.Count; i++)
            {
                if (this.bars.GetAt(i, out bar))
                {
                    if (this.Values.Mode == CValueProperty.ValueMode.Digit)
                    {
                        text = string.Format("{0:F1}", bar.Value);
                    }
                    else if ((this.Values.Mode == CValueProperty.ValueMode.Percent) && (totalValue > 0.0))
                    {
                        text = (bar.Value / totalValue).ToString("P1", CultureInfo.CurrentCulture);
                    }
                    if (text.Length > str3.Length)
                    {
                        str3 = text;
                    }
                }
            }
            SizeF ef = gr.MeasureString(text, this.Values.Font);
            if (ef.Width > sizeBar.Width)
            {
                float num4 = sizeBar.Width / ef.Width;
                emSize = this.Values.Font.Size * num4;
                if (emSize > 0f)
                {
                    this.Values.Font.Dispose();
                    this.Values.Font = null;
                    this.Values.Font = new Font(name, emSize, regular);
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (this.components != null))
            {
                this.components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void DrawBackground(Graphics gr, Bitmap bmpChart)
        {
            if (this.Background.PaintingMode == CBackgroundProperty.PaintingModes.LinearGradient)
            {
                LinearGradientBrush brush = new LinearGradientBrush(new Point(0, 0), new Point(0, bmpChart.Height), this.Background.GradientColor1, this.Background.GradientColor2);
                gr.FillRectangle(brush, new Rectangle(0, 0, bmpChart.Width, bmpChart.Height));
            }
            else if (this.Background.PaintingMode == CBackgroundProperty.PaintingModes.SolidColor)
            {
                gr.FillRectangle(new SolidBrush(this.Background.SolidColor), new Rectangle(0, 0, bmpChart.Width, bmpChart.Height));
            }
            else
            {
                gr.FillRectangle(new SolidBrush(this.Background.SolidColor), new Rectangle(0, 0, bmpChart.Width, bmpChart.Height));
            }
        }

        private void DrawBar(Graphics gr, RectangleF rectBar, HBarData bar)
        {
            if (rectBar.Height <= 0f)
            {
                rectBar.Height = 1f;
            }
            int alpha = (int) (185f + ((5f * rectBar.Width) / 24f));
            int num2 = (int) (10f + ((4f * rectBar.Width) / 24f));
            if (alpha > 0xff)
            {
                alpha = 0xff;
            }
            else if (alpha < 0)
            {
                alpha = 0;
            }
            if (num2 > 0xff)
            {
                num2 = 0xff;
            }
            else if (num2 < 0)
            {
                num2 = 0;
            }
            Color color = bar.Color;
            Color color2 = Color.FromArgb(50, 0, 0, 0);
            Color color3 = Color.FromArgb(num2, 0xff, 0xff, 0xff);
            Color color4 = Color.FromArgb(alpha, 0xff, 0xff, 0xff);
            Color darkerColor = this.GetDarkerColor(bar.Color, 0x55);
            Color color6 = this.GetDarkerColor(bar.Color, 100);
            RectangleF rect = new RectangleF(rectBar.Left, rectBar.Top - (rectBar.Height / 2f), rectBar.Width * 2f, rectBar.Height * 2f);
            GraphicsPath path = new GraphicsPath();
            path.AddEllipse(rect);
            PathGradientBrush brush = new PathGradientBrush(path);
            brush.CenterPoint = new PointF(rectBar.Right, rectBar.Top + (rectBar.Height / 2f));
            brush.CenterColor = color;
            brush.SurroundColors = new Color[] { color2 };
            RectangleF ef2 = new RectangleF(rectBar.Left, rectBar.Top, rectBar.Width / 2f, rectBar.Height);
            LinearGradientBrush brush2 = new LinearGradientBrush(new PointF(ef2.Right + 1f, ef2.Top), new PointF(ef2.Left - 1f, ef2.Top), color3, color4);
            gr.FillRectangle(new SolidBrush(darkerColor), rectBar);
            gr.FillRectangle(brush, rectBar);
            gr.FillRectangle(brush2, ef2);
            gr.DrawRectangle(new Pen(color6, 1f), rectBar.Left, rectBar.Top, rectBar.Width, rectBar.Height);
            if (this.Label.Visible)
            {
                float height = this.Label.Font.GetHeight(gr);
                gr.DrawString(bar.Label, this.Label.Font, new SolidBrush(this.Label.Color), new RectangleF(rectBar.X, rectBar.Bottom + this.nBarsGap, rectBar.Width, height));
            }
            if (this.Values.Visible)
            {
                string s = string.Empty;
                if (this.Values.Mode == CValueProperty.ValueMode.Digit)
                {
                    s = bar.Value.ToString("F1");
                }
                else if (this.Values.Mode == CValueProperty.ValueMode.Percent)
                {
                    double totalValue = this.bars.TotalValue;
                    if (totalValue > 0.0)
                    {
                        s = (bar.Value / totalValue).ToString("P1", CultureInfo.CurrentCulture);
                    }
                }
                float num5 = this.Values.Font.GetHeight(gr);
                gr.DrawString(s, this.Values.Font, new SolidBrush(this.Values.Color), new RectangleF(rectBar.X, (rectBar.Top - num5) - 1f, rectBar.Width + (2 * this.nBarsGap), num5));
            }
        }

        private void DrawBars(Graphics gr, Bitmap bmpChart)
        {
            RectangleF rectBar = new Rectangle();
            SizeF empty = (SizeF) Size.Empty;
            SizeF sizeBar = (SizeF) Size.Empty;
            float height = 0f;
            float num2 = 0f;
            float left = 0f;
            if (((this.description != null) && (this.label != null)) && (this.values != null))
            {
                int nBarsGap = this.nBarsGap;
                this.Description.SaveObject();
                this.Label.SaveObject();
                this.Values.SaveObject();
                if (this.SizingMode == BarSizingMode.AutoScale)
                {
                    if (this.bars.Count > 0)
                    {
                        this.nBarsGap = 4 + ((12 * bmpChart.Size.Width) / ((0x159 * this.bars.Count) * 7));
                    }
                    if (this.nBarsGap > 50)
                    {
                        this.nBarsGap = 50;
                    }
                    sizeBar = new SizeF((float) this.nBarWidth, (float) (bmpChart.Size.Height - (2 * this.nBarsGap)));
                    if (this.bars.Count > 0)
                    {
                        sizeBar.Width = (bmpChart.Size.Width - ((this.bars.Count + 1) * this.nBarsGap)) / this.bars.Count;
                    }
                    if (sizeBar.Width <= 0f)
                    {
                        sizeBar.Width = 24f;
                    }
                    this.CreateLabelFont(gr, sizeBar);
                    height = this.Label.Font.GetHeight(gr);
                    this.CreateValueFont(gr, sizeBar);
                    num2 = this.Values.Font.GetHeight(gr);
                    this.CreateDescFont(gr, (SizeF) bmpChart.Size);
                    empty = new SizeF((float) (bmpChart.Size.Width - (2 * this.nBarsGap)), this.description.Font.GetHeight(gr) + (2 * this.nBarsGap));
                    if (this.description.Visible)
                    {
                        sizeBar.Height -= empty.Height;
                    }
                    if (this.Label.Visible)
                    {
                        sizeBar.Height -= height;
                    }
                    if (this.Values.Visible)
                    {
                        sizeBar.Height -= num2;
                    }
                    left = base.ClientRectangle.Left;
                }
                else if (this.SizingMode == BarSizingMode.Normal)
                {
                    this.Values.RestoreObject();
                    this.nBarsGap = nBarsGap;
                    this.Description.RestoreObject();
                    this.Label.RestoreObject();
                    float num5 = this.description.Font.GetHeight(gr) + (2 * this.nBarsGap);
                    empty = new SizeF((float) (bmpChart.Size.Width - (2 * this.nBarsGap)), num5);
                    height = this.Label.Font.GetHeight(gr);
                    num2 = this.Values.Font.GetHeight(gr);
                    sizeBar = new SizeF((float) this.nBarWidth, (float) (bmpChart.Size.Height - (2 * this.nBarsGap)));
                    if (this.Description.Visible)
                    {
                        sizeBar.Height -= empty.Height;
                    }
                    if (this.Label.Visible)
                    {
                        sizeBar.Height -= height;
                    }
                    if (this.Values.Visible)
                    {
                        sizeBar.Height -= num2;
                    }
                    left = ((bmpChart.Size.Width - (this.bars.Count * sizeBar.Width)) - ((this.bars.Count + 1) * this.nBarsGap)) / 2f;
                }
                if (this.description.Visible)
                {
                    StringFormat genericDefault = StringFormat.GenericDefault;
                    genericDefault.LineAlignment = StringAlignment.Center;
                    genericDefault.Alignment = StringAlignment.Center;
                    genericDefault.Trimming = StringTrimming.None;
                    genericDefault.FormatFlags = StringFormatFlags.LineLimit | StringFormatFlags.NoWrap;
                    gr.DrawString(this.description.Text, this.description.Font, new SolidBrush(this.description.Color), new RectangleF((float) this.nBarsGap, bmpChart.Height - empty.Height, empty.Width, empty.Height), genericDefault);
                }
                for (int i = 0; i < this.bars.Count; i++)
                {
                    HBarData data;
                    if (this.bars.GetAt(i, out data))
                    {
                        rectBar.Width = sizeBar.Width;
                        rectBar.Height = (float) ((data.Value * sizeBar.Height) / this.bars.MaxValue);
                        rectBar.X = (left + (i * sizeBar.Width)) + ((i + 1) * this.nBarsGap);
                        rectBar.Y = (this.nBarsGap + sizeBar.Height) - rectBar.Height;
                        if (this.Values.Visible)
                        {
                            rectBar.Y += num2;
                        }
                        data.BarRect = new RectangleF(rectBar.Left, 0f, sizeBar.Width, (float) base.ClientRectangle.Height);
                        this.DrawBar(gr, rectBar, data);
                    }
                }
                this.nBarsGap = nBarsGap;
                this.Description.RestoreObject();
                this.Label.RestoreObject();
                this.Values.RestoreObject();
            }
        }

        private void DrawChart(ref Bitmap bmp)
        {
            if (bmp == null)
            {
                bmp = new Bitmap(base.ClientSize.Width, base.ClientSize.Height);
            }
            using (Graphics graphics = Graphics.FromImage(bmp))
            {
                this.DrawBackground(graphics, bmp);
                this.DrawBars(graphics, bmp);
            }
        }

        public bool GetAt(int nIndex, out HBarData bar)
        {
            return this.bars.GetAt(nIndex, out bar);
        }

        private Color GetDarkerColor(Color color, byte intensity)
        {
            int num = color.R - intensity;
            int num2 = color.G - intensity;
            int num3 = color.B - intensity;
            if ((num > 0xff) || (num < 0))
            {
                num *= -1;
            }
            if ((num2 > 0xff) || (num2 < 0))
            {
                num2 *= -1;
            }
            if ((num3 > 0xff) || (num3 < 0))
            {
                num3 *= -1;
            }
            return Color.FromArgb(0xff, (byte) num, (byte) num2, (byte) num3);
        }

        private void InitializeComponent()
        {
            base.SuspendLayout();
            base.AutoScaleDimensions = new SizeF(6f, 13f);
            base.AutoScaleMode = AutoScaleMode.Font;
            this.BackColor = SystemColors.Control;
            base.Name = "HBarChart";
            base.Paint += new PaintEventHandler(this.OnPaint);
            base.Resize += new EventHandler(this.OnSize);
            base.MouseMove += new MouseEventHandler(this.OnMouseMove);
            base.ResumeLayout(false);
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            string str = string.Empty;
            double totalValue = this.bars.TotalValue;
            string str2 = string.Empty;
            for (int i = 0; i < this.bars.Count; i++)
            {
                HBarData data;
                if (this.bars.GetAt(i, out data) && data.BarRect.Contains((PointF) e.Location))
                {
                    if (totalValue > 0.0)
                    {
                        str2 = (data.Value / totalValue).ToString("P2", CultureInfo.CurrentCulture);
                    }
                    str = string.Format("{0}\r\n{1}", data.Value, str2);
                    this.tooltip.Hide(this);
                    this.tooltip.RemoveAll();
                    this.tooltip.ToolTipTitle = data.Label;
                    this.tooltip.SetToolTip(this, str.ToString());
                    return;
                }
            }
            this.tooltip.Hide(this);
            this.tooltip.RemoveAll();
        }

        private void OnPaint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            if (this.bmpBackBuffer == null)
            {
                this.DrawChart(ref this.bmpBackBuffer);
            }
            if (this.bmpBackBuffer != null)
            {
                e.Graphics.DrawImageUnscaled(this.bmpBackBuffer, 0, 0);
            }
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
        }

        private void OnSize(object sender, EventArgs e)
        {
            this.RedrawChart();
        }

        public bool Print(bool bFitToPaper, string strDocName)
        {
            Bitmap bitmap;
            CPrinter printer = new CPrinter();
            printer.ShowOptions();
            printer.Document.DocumentName = strDocName;
            printer.FitToPaper = bFitToPaper;
            if (bFitToPaper)
            {
                bitmap = new Bitmap(printer.Document.DefaultPageSettings.Bounds.Width, printer.Document.DefaultPageSettings.Bounds.Height);
            }
            else
            {
                bitmap = (Bitmap) this.bmpBackBuffer.Clone();
            }
            this.DrawChart(ref bitmap);
            printer.BmpBuffer = bitmap;
            bool flag = false;
            flag = printer.Print();
            bitmap.Dispose();
            bitmap = null;
            return flag;
        }

        public void RedrawChart()
        {
            if (this.bmpBackBuffer != null)
            {
                this.bmpBackBuffer.Dispose();
                this.bmpBackBuffer = null;
            }
            this.Refresh();
        }

        public bool RemoveAt(int nIndex)
        {
            return this.bars.RemoveAt(nIndex);
        }

        public CBackgroundProperty Background
        {
            get
            {
                return this.background;
            }
            set
            {
                this.background = value;
            }
        }

        public int BarsGap
        {
            get
            {
                return this.nBarsGap;
            }
            set
            {
                this.nBarsGap = value;
            }
        }

        public int BarWidth
        {
            get
            {
                return this.nBarWidth;
            }
            set
            {
                this.nBarWidth = value;
                this.Refresh();
            }
        }

        public int Count
        {
            get
            {
                return this.bars.Count;
            }
        }

        public CDescriptionProperty Description
        {
            get
            {
                return this.description;
            }
            set
            {
                this.description = value;
            }
        }

        public CLabelProperty Label
        {
            get
            {
                return this.label;
            }
            set
            {
                this.label = value;
            }
        }

        public CValueProperty Values
        {
            get
            {
                return this.values;
            }
            set
            {
                this.values = value;
            }
        }

        public enum BarSizingMode
        {
            Normal,
            AutoScale
        }
    }
}

